#pragma once

#include <boostext/queue.hpp>
#include <services/provider.hpp>
#include <logger/stream.hpp>
#include <db_schema/Connection.hpp>
#include <db_schema/RDBMS.hpp>

#include "exports.hpp"
#include "Crawler.h"
#include "Scheduler.h"
#include "PluginLoader.h"
#include "DatabaseDataProvider.hpp"
#include "DatabaseUrlProvider.hpp"
#include "CoreDataProcessor.h"




class CRAWLER_API Bot
	: public boost::noncopyable
{
public:

	typedef boost::shared_ptr<Bot>         Ptr;
	typedef boost::shared_ptr<const Bot>   const_Ptr;
	typedef QList<PluginLoader::Ptr>       Plugins;

private:

	//
	// Logging
	//

	logger::stream::ptr   m_logger;

	//
	// Loaded Plugins
	//

	Plugins            m_plugins;


	//
	// Provider
	//

	db::Connection::Ptr         m_connection;
	DatabaseDataProvider::Ptr   m_coreDataProvider;
	DatabaseUrlProvider::Ptr    m_coreUrlProvider;


	//
	// Subsystems
	//

	Crawler                  m_crawler;
	Scheduler                m_scheduler;
	CoreDataProcessor::Ptr   m_coreProcessor;


	//
	// Statistical Information
	//

	const QTime              m_startTime;

public:

	Bot(services::provider::const_ptr provider, db::Connection::Ptr connection);
	~Bot();



	/**
	 * @returns the list of loaded plugins
	 */
	Plugins plugins() const;



	/**
	 * Adds the given processor to the scheduler.
	 */
	void add(DataProcessor::Ptr processor);

	/**
	 * Adds the given url to the crawler.
	 */
	void add(QUrl url);

	/**
	 * Get the time this bot has been started.
	 */
	const QTime &startTime() const;



	/**
	 * Get a list of all active Requests (their respective URLs).
	 */
	QList<QUrl> activeRequests();




	/**
	 * Get the number of completed requests.
	 */
	quint64 numCompletedRequests() const;

	/**
	* Get the number of failed requests (either through a network error,
	* or because the request didn't contain wanted data).
	*/
	quint64 numFilteredReplies() const;

	/**
	 * Get the number of active requests.
	 */
	int numActiveRequests() const;

	/**
	 * Get the number of pending URLs (not requested yet).
	 */
	int numPendingUrls() const;



	/**
	 * Get the number of processed URLs.
	 */
	quint64 numProcessedUrls() const;

	/**
	 * Get the number of filtered URLs.
	 */
	quint64 numFilteredUrls() const;



	/**
	 * Get the average of completed requests per second.
	 */
	float requestRate() const;

	/**
	 * Get the current download rate in kb/s
	 */
	float downloadRate() const;

	/**
	 * Get the current upload rate in kb/s
	 */
	float uploadRate() const;

private:

	void loadPlugins();

	static db::TableDL::const_Ptr dataTable(db::Connection::Ptr connection);
	static db::TableDL::const_Ptr urlTable(db::Connection::Ptr connection);
};
///////////////////////////////////////////////////////////////////////////////////////////////////
